/**
 * 
 */
package org.swing.utility.jai.util;

import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;
import javax.media.jai.JAI;
import javax.media.jai.OpImage;
import javax.media.jai.RenderedOp;

import com.sun.media.jai.codec.SeekableStream;

/**
 * @author Quynh Nhu
 * 
 */
public class ImageResizerJAI {
	private byte[] image;

	public ImageResizerJAI() {
		System.setProperty("com.sun.media.jai.disableMediaLib", "true");
	}

	public byte[] resize(String img, int targetWidth, int targetHeight)
			throws IOException {
		return resize(new File(img), targetWidth, targetHeight);
	}

	public byte[] resize(File f, int targetWidth, int targetHeight)
			throws IOException {
		return resize(ImageIO.read(f), targetWidth, targetHeight);
	}

	public byte[] resize(BufferedImage img, int targetWidth, int targetHeight)
			throws IOException {
		// convert BufferedImage to ByteArray
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ImageIO.write(img, "jpeg", baos);
		return resize(baos.toByteArray(), targetWidth, targetHeight);
	}

	public byte[] resize(byte[] img, int targetWidth, int targetHeight)
			throws IOException {
		InputStream imageInputStream = new ByteArrayInputStream(img);
		// read in the original image from an input stream
		SeekableStream seekableImageStream = SeekableStream.wrapInputStream(
				imageInputStream, true);
		RenderedOp originalImage = JAI.create("stream", seekableImageStream);
		((OpImage) originalImage.getRendering()).setTileCache(null);
		double scale = getImageScale(originalImage.getWidth(),
				originalImage.getHeight(), targetWidth, targetHeight);
		ParameterBlock paramBlock = new ParameterBlock();
		paramBlock.addSource(originalImage); // The source image
		paramBlock.add(scale); // The xScale
		paramBlock.add(scale); // The yScale
		paramBlock.add(0.0); // The x translation
		paramBlock.add(0.0); // The y translation
		RenderingHints qualityHints = new RenderingHints(
				RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_QUALITY);
		RenderedOp resizedImage = JAI.create("SubsampleAverage", paramBlock,
				qualityHints);
		// lastly, write the newly-resized image to an output stream, in a
		// specific encoding

		ByteArrayOutputStream encoderOutputStream = new ByteArrayOutputStream();

		JAI.create("encode", resizedImage, encoderOutputStream, "JPEG", null);

		// Export to Byte Array

		image = encoderOutputStream.toByteArray();

		encoderOutputStream.close();

		// free resources

		seekableImageStream.close();

		resizedImage.dispose();

		originalImage.dispose();

		return image;

	}

	public void write(String img, String format) throws IOException {

		write(new File(img), format);

	}

	public void write(File f, String format) throws IOException {

		FileOutputStream fos = null;

		if (image != null) {

			new File(f.getParent()).mkdirs();

			try {

				fos = new FileOutputStream(f);

				fos.write(image);

				fos.close();

			} catch (Exception e) {

			} finally {

				if (fos != null)

					fos.close();

			}

		}

	}

	private double getImageScale(int sourceWidth, int sourceHeight,

	int targetWidth, int targetHeight) {

		double scalex = (double) targetWidth / sourceWidth;

		double scaley = (double) targetHeight / sourceHeight;

		return Math.max(scalex, scaley);

	}
	
	public static void main(String[] args) {
		String path = "/home/lqnhu/TEST/31856_a015376-00149.j2k";
	}

}
